﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace DARE
{
    public class CSkyMgr
    {
        #region fields

        private Dictionary<string, ASky> m_skies;
        private ASky m_activeSky;
        private CRender3D m_render3D;

        #endregion

        #region properties

        public ASky ActiveSky
        {
            get { return m_activeSky; }
            set { m_activeSky = value; }
        }

        #endregion

        #region ctor

        public CSkyMgr(CRender3D render3D)
        {
            m_render3D = render3D;
            m_skies = new Dictionary<string, ASky>();
            m_activeSky = null;
        }

        #endregion

        #region methods

        public List<ASky> GetAllSkies()
        {
            return m_skies.Values.ToList();
        }

        public CSkyMgr RegisterSky(ASky sky)
        {
            if (!m_skies.ContainsKey(sky.Name))
                m_skies.Add(sky.Name, sky);
            else
                m_skies[sky.Name] = sky;
            return this;
        }

        //public ASky CreateSkybox(string name, string cubeMap)
        //{
        //    if (m_skies.ContainsKey(name))
        //        return m_skies[name];
        //    ASky sky = new CSkybox(m_render3D, cubeMap);
        //    sky.TextureName = cubeMap;
        //    if (m_skies.Count == 0)
        //        m_activeSky = sky;
        //    m_skies.Add(name, sky);
        //    return sky;
        //}

        public ASky CreateSkyPlane(string name, Texture2D text)
        {
            if (m_skies.ContainsKey(name))
                return m_skies[name];
            ASky sky = new CSkyPlane(m_render3D, text);
            sky.Name = name;
            if (m_skies.Count == 0)
                m_activeSky = sky;
            m_skies.Add(name, sky);
            return sky;
        }

        public ASky CreateSkybox(string name, TextureCube cubeMap)
        {
            if (m_skies.ContainsKey(name))
                return m_skies[name];
            ASky sky = new CSkybox(m_render3D, cubeMap);

            sky.Name = name;
            sky.Texture = cubeMap;
            if (m_skies.Count == 0)
                m_activeSky = sky;
            m_skies.Add(name, sky);
            return sky;
        }

        /// <summary>
        /// Create a skybox with 6 textures for the faces.
        /// </summary>
        /// <param name="skypath">
        /// The path of the 6 textures (the common name, for example if the names are
        /// "cloudy_sky_UP.png", "cloudy_sky_DN.png", "cloudy_sky_LF.png", "cloudy_sky_RT.png", "cloudy_sky_BK.png", "cloudy_sky_FR.png" 
        /// the skypath to be given is "cloudy_sky".
        /// Each texture has to be named with a suffix:
        /// For the left one : "_LF".
        /// For the right one : "_RT".
        /// For the top one : "_UP".
        /// For the bottom one : "_DN".
        /// For the front one : "_FR".
        /// For the back one : "_BK".
        /// </param>
        /// <seealso cref="CSkybox"/>
        public ASky CreateSkybox(string name, string skypath)
        {
            if (m_skies.ContainsKey(name))
                return m_skies[name];
            ASky sky = new CSkybox(m_render3D, skypath);
            sky.Name = name;
            //sky.Texture = cubeMap;
            if (m_skies.Count == 0)
                m_activeSky = sky;
            m_skies.Add(name, sky);
            return sky;
        }

        public ASky CreateSkybox(string name, string up, string down, string front, string back, string left, string right)
        {
            if (m_skies.ContainsKey(name))
                return m_skies[name];
            ASky sky = new CSkybox(m_render3D, up, down, front, back, left, right);
            sky.Name = name;
            //sky.Texture = cubeMap;
            if (m_skies.Count == 0)
                m_activeSky = sky;
            m_skies.Add(name, sky);
            return sky;
        }

        public ASky CreateSkybox(string name, Texture2D up, Texture2D down, Texture2D front, Texture2D back, Texture2D left, Texture2D right)
        {
            if (m_skies.ContainsKey(name))
                return m_skies[name];
            ASky sky = new CSkybox(m_render3D, up, down, front, back, left, right);
            sky.Name = name;
            //sky.Texture = cubeMap;
            if (m_skies.Count == 0)
                m_activeSky = sky;
            m_skies.Add(name, sky);
            return sky;
        }

        public ASky GetSky(string name)
        {
            return m_skies[name];
        }

        public ASky UnregisterSky(string name)
        {
            if (m_skies.ContainsKey(name))
            {
                ASky sky = m_skies[name];
                m_skies.Remove(name);
                return sky;
            }
            return null;
        }

        public ASky SetActiveSky(string name)
        {
            m_activeSky = m_skies[name];
            return m_activeSky;
        }

        public ASky SetActiveSky(ASky sky)
        {
            m_activeSky = sky;
            if (!m_skies.ContainsKey(sky.Name))
                RegisterSky(sky);
            return sky;
        }

        #endregion

        #region run

        public void Update(GameTime gameTime)
        {
            if (m_activeSky != null)
                m_activeSky.Update(gameTime);
        }

        public void Draw(GameTime gameTime)
        {
            if (m_activeSky != null)
            {
                // current render3d settings
                m_activeSky.FillMode = m_render3D.FillMode;
                m_activeSky.CullMode = m_render3D.FillMode == FillMode.WireFrame ? CullMode.None : CullMode.CullCounterClockwiseFace;
                m_activeSky.Draw(gameTime);
            }
        }

        #endregion
    }
}
